package com.litchi.schedule;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.litchi.entity.Lottery;
import com.litchi.entity.Match;
import com.litchi.persistence.repo.LotteryRepository;
import com.litchi.utils.LotteryUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.jms.JMSException;
import javax.jms.Message;
import java.io.IOException;
import java.text.ParseException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by huash on 2016/5/7.
 */
@Component
@Slf4j
public class ProbabilityCrawlTask {
    @Autowired
    private LotteryRepository lotteryRepository;

    @Autowired(required = false)
    private JmsTemplate jmsTemplate;

    @Scheduled(fixedDelay = 30 * 60 * 1000)
    public void crawlProbabilities() throws IOException, ParseException {
        log.info("Starting crawl probabilities");

        Document doc = Jsoup.connect("http://www.500.com/").get();
        Element table = doc.select("#duizhen_tb").first();
        Elements trs = table.select("tr");

        Calendar cal = Calendar.getInstance();
        List<Match> matches = new ArrayList<>(20);
        for (Element tr : trs) {
            log.info("Parsing: " + tr);
            Elements tds = tr.select("td");
            Integer order = Integer.parseInt(tds.get(0).text().trim());
            String vs = tds.get(1).text().replaceAll("\\[[^\\[\\]]*\\]", "");
            String[] teams = vs.split("(VS)|(\\d+\\s*:\\s*\\d+)");
            Date time = DateUtils.parseDate(tds.get(2).text().trim(), "MM-dd HH:mm");
            time = DateUtils.setYears(time, cal.get(Calendar.YEAR));
            Double win = Double.parseDouble(tds.get(4).select("span").get(0).text().trim());
            Double lost = Double.parseDouble(tds.get(4).select("span").get(1).text().trim());
            Double tie = Double.parseDouble(tds.get(4).select("span").get(2).text().trim());
            Match match = new Match(order, teams[0].trim(), teams[1].trim(), time, win, lost, tie, getScoreOfVS(vs));
            LotteryUtils.fillPropertiesOfMatch(match);
            matches.add(match);
            log.debug("Found match: " + match);
        }

        Integer round = Integer.parseInt(doc.select("#duizhen_sel").select("[selected=selected]").first().text().trim().replaceAll("\\D", ""));
        Lottery lottery = new Lottery(round, cal.getTime(), matches);
        LotteryUtils.fillPropertiesOfLottery(lottery);

        List<Lottery> existingLotteries = lotteryRepository.findFirst1ByRound(round, new Sort(Sort.Direction.DESC, "updateTime"));
        boolean exists = existingLotteries.stream().anyMatch(s -> {
            return s.sameAs(lottery);
        });

        if (!exists) {
            lotteryRepository.save(lottery);
            sendMessage(lottery);
            log.info("Saving lottery: " + lottery);
        } else {
            log.info("Not updated: " + lottery);
        }
    }

    private String getScoreOfVS(String vs) {
        Pattern p = Pattern.compile("\\d+\\s*:\\s*\\d+");
        Matcher m = p.matcher(vs);
        String result = "-";
        if (m.find()) {
            result = vs.substring(m.start(), m.end());
        }
        log.debug(String.format("Score of %s is %s", vs, result));
        return result;
    }

    private void sendMessage(Lottery lottery) {
        ObjectMapper m = new ObjectMapper();
        Map<String, Object> lotteryMap = m.convertValue(lottery, Map.class);

        jmsTemplate.convertAndSend("lottery-destination", lotteryMap, new org.springframework.jms.core.MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws JMSException {
                message.setJMSCorrelationID("2210202");
                message.setIntProperty("p1", 1);
                return message;
            }
        });
    }
}
